#include "myStdio.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>


//设置默认权限
#define FILE_MODE 0666

//实现一下三种方式，"w","r","a"
_FILE* _fopen(const char* filename, const char* flag)
{
    assert(filename);
    assert(flag);
    // 1、用open打开文件
    int fd = -1; //文件描述符
    int flags = 0;//打开方式

    if(strcmp(flag, "w") == 0)
    {
        flags = (O_CREAT | O_WRONLY | O_TRUNC); //设置打开方式
        fd = open(filename, flags, FILE_MODE);
    }
    else if(strcmp(flag, "r") == 0)
    {
        flags = O_RDONLY; 
        fd = open(filename, flags);
    }
    else if(strcmp(flag, "a") == 0)
    {
        flags = (O_CREAT | O_WRONLY | O_APPEND);
        fd = open(filename, flags, FILE_MODE);
    }
    else //err
    {
        //设置errno，这里我就简化不做处理
        return NULL; 
    }

    if(fd == -1)  //open err
        return NULL;

    //2、malloc _FILE对象并设置对应的文件描述符，然后返回给上层
    _FILE* fp = (_FILE*)malloc(sizeof(_FILE));
    if(fp == NULL) // malloc error
        return NULL; 
    
    //初始化成员字段
    fp->fileno = fd;
    fp->flag = FLUSH_ALL;
    fp->outpos = 0;

    return fp;
}

int _fwrite(_FILE* fp, const char* str, int len)
{
    //将内容写入缓冲区
    //由于采用静态数组，这里暂时不对异常情况做处理
    memcpy(&fp->outbuffer[fp->outpos], str, len); 
    fp->outpos += len;

    //根据不同刷新策略进行写入操作
    if(fp->flag & FLUSH_NOW)
    {
        write(fp->fileno, fp->outbuffer, fp->outpos);
        fp->outpos = 0;
    }
    else if(fp->flag & FLUSH_LINE)
    {
        if(fp->outbuffer[fp->outpos-1] == '\n'){
            write(fp->fileno, fp->outbuffer, fp->outpos);
            fp->outpos = 0;
        }
    }
    else if(fp->flag & FLUSH_ALL)
    {
        if(fp->outpos == SIZE)
        {
            write(fp->fileno, fp->outbuffer, fp->outpos);
            fp->outpos = 0;
        }
    }

    return len;
}

void _fclose(_FILE* fp)
{
    assert(fp);

    _fflush(fp); // 刷新缓冲区数据

    close(fp->fileno);
    free(fp);
}

void _fflush(_FILE* fp)
{
    assert(fp);
    //缓冲区内有数据就写入到文件中
    if(fp->outpos > 0)
    {
        write(fp->fileno, fp->outbuffer, fp->outpos);
        fp->outpos = 0;
    }
}


//行刷新的处理逻辑
        // else
        // {
        //     "abc\nacd"
        //     for(int i = 0; i < fp->outpos; i++)
        //     {
        //         if(fp->outbuffer[i] == '\n')
        //         {
        //             write(fp->fileno, fp->outbuffer, i);
        //             fp->outpos -= i;
        //             int n = 0;
        //             int m = fp->outpos + i
        //             while(i < m)
        //             {
        //                 fp->outbuffer[n++] = fp->outbuffer[i++];
        //             }
        //             break;
        //         }
        //     }
        // }